Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add "Remember Me" checkbox to the login form #440

Merged
merged 9 commits into from
Nov 1, 2024

Conversation

haseebzaki-07
Copy link
Contributor

@haseebzaki-07 haseebzaki-07 commented Oct 30, 2024

fixes #276

This PR adds the remember me feature while logging in so that the token can be set for a longer duration.
Modifications in the login controller and the login frontend page.

Screenshot 2024-10-30 164929

2024-10-30.16-49-05.mp4

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a "Remember Me" option for user login, allowing extended session duration.
    • Added a new "PROFILE" menu item in the navigation bar linking to the user dashboard.
    • Implemented a new dashboard component to display user reservations.
    • Enhanced event registration with authentication checks.
    • Added a new route for the dashboard in the router configuration.
  • Bug Fixes

    • Corrected a typo in the error middleware import.
  • Documentation

    • Updated contributor information in the README file.
    • Streamlined troubleshooting and contact sections for clarity.
  • Chores

    • Added a new dependency for JWT decoding in the frontend.
  • Style

    • Minor formatting updates for consistency in various files.

Copy link

vercel bot commented Oct 30, 2024

@haseebzaki-07 is attempting to deploy a commit to the bunty's projects Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Contributor

coderabbitai bot commented Oct 30, 2024

Walkthrough

The pull request encompasses multiple changes across various files in the PlayCafe project. Key updates include modifications to the README.md file to reflect new contributors and a refined troubleshooting section. The backend has seen enhancements in customer authentication and reservation handling, including new optional parameters and middleware for improved security. Additionally, frontend components have been updated to incorporate a "Remember Me" feature for user login, along with new routes and components for managing user reservations. Overall, the changes focus on improving user experience and system functionality.

Changes

File Change Summary
README.md Updated contributor entries; modified troubleshooting and contact sections for clarity.
backend/.env.example Removed environment variable declarations for backend configuration.
backend/controller/customer.controller.js Enhanced login functionality with rememberMe parameter; added resetPassword method.
backend/controller/reservation.controller.js Updated reservation logic to include userId; added fetchUserReservations method.
backend/index.js Modified CORS configuration to allow credentials; corrected typo in error middleware import.
backend/middlewares/authCustomer.js Made authenticateCustomer asynchronous; improved error handling and user verification.
backend/middlewares/sessionMiddleware.js Streamlined session validation logic; updated error response format.
backend/models/customer.model.js Added reservations field to customerSchema; minor formatting changes.
backend/models/reservation.model.js Added required customer field to reservationSchema.
backend/routes/eventRouter.js Added authenticateCustomer middleware to event routes for authentication.
backend/routes/reservationRouter.js Updated createReservation route to include userId; added route for fetching user reservations.
frontend/package.json Added dependency for jwt-decode.
frontend/src/components/Pages/Dashboard.tsx Introduced Profile component for displaying user reservations.
frontend/src/components/Pages/Event.jsx Updated event registration logic to check for authentication token.
frontend/src/components/Pages/Login.jsx Added "Remember Me" checkbox; updated cookie expiration logic based on this option.
frontend/src/components/Shared/Navbar.jsx Added "PROFILE" menu item; updated logout functionality.
frontend/src/router/index.jsx Added route for /dashboard to render Profile component.

Assessment against linked issues

Objective Addressed Explanation
Add "Remember Me" checkbox to the login form (#276)

Possibly related PRs

Suggested labels

enhancement, level2, gssoc-ext, hacktoberfest accepted

Suggested reviewers

  • RamakrushnaBiswal

🐰 In the garden, changes bloom,
New features sprout, dispelling gloom.
With "Remember Me," we hop with glee,
Reservations now, as easy as can be!
Contributors shine, their names in light,
PlayCafe grows, oh what a delight! 🌼


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between c0ceedb and 41ca0eb.

📒 Files selected for processing (1)
  • frontend/src/components/Pages/Event.jsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/components/Pages/Event.jsx

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

Thank you for submitting your pull request! 🙌 We'll review it as soon as possible. In the meantime, please ensure that your changes align with our CONTRIBUTING.md. If there are any specific instructions or feedback regarding your PR, we'll provide them here. Thanks again for your contribution! 😊

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 21

🧹 Outside diff range and nitpick comments (18)
backend/middlewares/sessionMiddleware.js (1)

5-8: Consider adding error codes to the response.

While the JSON error response is good, adding an error code would help with error handling on the client side.

 res.status(401).json({
   success: false,
   message: "Invalid session. Please log in again.",
+  errorCode: "SESSION_INVALID"
 });
backend/models/reservation.model.js (1)

17-21: Consider data migration strategy for existing reservations.

Since the new customer field is marked as required, existing reservations in the database will need to be migrated to include this field.

Would you like me to help create a migration script or open an issue to track this task?

backend/routes/reservationRouter.js (2)

Line range hint 10-19: Update API documentation to reflect new endpoints.

The welcome message's endpoints section is outdated. It still shows /create [POST] but the actual endpoint is now /create/:id [POST]. Additionally, the new /get/:id [GET] endpoint is missing from the documentation.

Apply this diff to update the documentation:

     endpoints: {
-      createReservation: "/create [POST]",
+      createReservation: "/create/:id [POST]",
+      getUserReservations: "/get/:id [GET]"
     },

7-8: Consider rate limiting for reservation endpoints.

Since these endpoints are now authenticated per user, consider adding rate limiting to prevent abuse.

Consider implementing rate limiting middleware:

  1. Use express-rate-limit package
  2. Set appropriate limits per user/IP
  3. Apply the middleware to these sensitive endpoints

Would you like me to provide an example implementation?

backend/routes/eventRouter.js (3)

31-31: Consider keeping the /all route public.

The /all route typically serves public event listings. Adding authentication might unnecessarily restrict access to event information that should be publicly available.

Consider maintaining this as a public route unless there's a specific requirement for authenticated access to event listings.


30-32: Fix spacing in middleware chain.

There should be spaces after commas in the middleware chain for better readability.

Apply this formatting fix:

-router.post("/create",authenticateCustomer, createEvent);
-router.get("/all",authenticateCustomer, getEvents);
-router.get("/delete",authenticateCustomer, deleteEvent);
+router.post("/create", authenticateCustomer, createEvent);
+router.get("/all", authenticateCustomer, getEvents);
+router.get("/delete", authenticateCustomer, deleteEvent);

28-29: Remove extra empty lines.

Multiple consecutive empty lines affect code readability.

Remove one of the empty lines to maintain consistent spacing.

backend/models/customer.model.js (1)

52-57: New reservations field looks good but needs documentation.

The addition of the reservations field establishes a proper relationship with the Reservation model. However, consider adding JSDoc comments to document this relationship.

+    /**
+     * Array of reservations associated with this customer
+     * @type {Array<mongoose.Schema.Types.ObjectId>}
+     */
     reservations: [
       {
         type: Schema.Types.ObjectId,
         ref: "Reservation", // Link to Reservation schema
       },
     ],
frontend/src/router/index.jsx (1)

25-25: Consider aligning component naming with file naming.

The component is imported as Profile from a file named Dashboard.tsx. This naming inconsistency could lead to confusion. Consider either:

  • Renaming the file to Profile.tsx to match the component name, or
  • Renaming the component to Dashboard to match the file name
backend/index.js (1)

Line range hint 47-54: Consider updating session configuration for "Remember Me" feature.

The current session configuration has a fixed 24-hour cookie maxAge. For the "Remember Me" feature, consider implementing dynamic session duration:

  • Short duration (e.g., 24 hours) for regular login
  • Extended duration (e.g., 30 days) when "Remember Me" is checked

Example implementation:

app.use(
  session({
    secret: process.env.SECRET_KEY,
    resave: false,
    saveUninitialized: false,
    cookie: {
      // Make maxAge configurable based on "Remember Me"
      maxAge: req?.body?.rememberMe ? 30 * 24 * 60 * 60 * 1000 : 24 * 60 * 60 * 1000,
      secure: process.env.NODE_ENV === 'production',
    },
    store: MongoStore.create({
      mongoUrl: process.env.MONGO_URI,
    }),
  })
);
frontend/src/components/Pages/Dashboard.tsx (2)

6-10: Consider renaming the component to match the file name.

The component is named Profile while the file is named Dashboard.tsx. This inconsistency could lead to confusion. Consider renaming the component to Dashboard to maintain consistency.

-function Profile() {
+function Dashboard() {

29-29: Remove console.log statement.

Remove debugging console.log statement before production deployment.

-        console.log("Decoded userId:", userId); // Debugging line
backend/controller/customer.controller.js (2)

115-123: Consider minimizing the JWT payload.

While the implementation is functional, consider reducing the JWT payload size by including only essential claims. The email might not be necessary in the token if you're already storing the user ID.

 const payload = {
   sub: customer._id,
   name: customer.name,
   role: "customer",
-  email: customer.email,
 };

Line range hint 171-177: Improve logout security for "Remember Me" sessions.

The current logout implementation using req.session.destroy() doesn't invalidate the JWT token. Long-lived tokens from "Remember Me" sessions will remain valid until expiration.

Consider implementing one of these solutions:

  1. Add token to a blocklist/denylist on logout
  2. Use token rotation with refresh tokens
  3. Clear the auth cookie on logout

Here's how to properly clear the auth cookie:

 async function logout(req, res){
-  req.session.destroy((err) => {
-    if (err) {
-      return res.status(500).send("Failed to log out.");
-    }
-    res.send("Logged out successfully!");
-  });
+  res.clearCookie('authToken', {
+    httpOnly: true,
+    secure: process.env.NODE_ENV === "production",
+    sameSite: "strict",
+    path: "/"
+  });
+  res.status(200).json({ message: "Logged out successfully" });
 }
frontend/src/components/Shared/Navbar.jsx (2)

Line range hint 28-31: Optimize useEffect to prevent unnecessary re-renders.

The useEffect hook without a dependency array will run on every render, which could cause performance issues. Consider adding an empty dependency array if you only want to run this once, or specific dependencies if you want to run it when certain values change.

  useEffect(() => {
    setToken(Cookies.get('authToken'));
-  });
+  }, []);

Line range hint 11-11: Consider enhancing token handling for Remember Me feature.

The current token management doesn't distinguish between regular and remembered tokens. To properly support the Remember Me feature:

  1. Consider adding a check for token expiration
  2. Handle token refresh if needed
  3. Ensure proper cleanup of both regular and remembered tokens during logout

Consider implementing a centralized auth service to handle these token management complexities. Example structure:

// auth.service.js
export const AuthService = {
  getToken: () => {
    const token = Cookies.get('authToken');
    if (!token) return null;
    
    // Add token validation/refresh logic here
    return token;
  },
  
  logout: async () => {
    // Clean up all auth-related cookies
    Cookies.remove('authToken');
    Cookies.remove('rememberMe');
    // Additional cleanup as needed
  }
};

Also applies to: 51-63

README.md (2)

Line range hint 283-503: Replace hard tabs with spaces in the contributors table.

The contributors table uses hard tabs for indentation which is flagged by markdownlint. While this doesn't affect the rendered output, it's best practice to maintain consistent formatting.

Replace all hard tabs with spaces (2 or 4 spaces per indentation level) in the table structure.

🧰 Tools
🪛 Markdownlint

459-459: Column: 1
Hard tabs

(MD010, no-hard-tabs)


460-460: Column: 1
Hard tabs

(MD010, no-hard-tabs)


Line range hint 1-603: Document the "Remember Me" feature in the README.

The PR adds a "Remember Me" checkbox to the login form, but this new feature is not documented in the README. Consider adding:

  1. A mention in the Features table
  2. Usage instructions in the Usage section
  3. Any relevant API endpoints in the API Documentation section

Add a new entry in the Features table:

 | Feature                       | Description                                                   |
 |-------------------------------|---------------------------------------------------------------|
+| 🔐 Remember Me                | Stay logged in for extended periods with the Remember Me option|

Add usage instructions:

 ## 📌 Usage
 Once the application is running, you can:
 - Navigate through the website to explore different sections.
 - Book a table for an event.
 - Contact us for inquiries.
+- Use the "Remember Me" option during login to stay signed in.

Add API documentation:

 | HTTP Method | Endpoint              | Description                                            |
 |-------------|-----------------------|--------------------------------------------------------|
+| POST        | `/api/auth/login`     | Authenticates user with optional "Remember Me" duration |
🧰 Tools
🪛 Markdownlint

459-459: Column: 1
Hard tabs

(MD010, no-hard-tabs)


460-460: Column: 1
Hard tabs

(MD010, no-hard-tabs)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 7aa1cc1 and c0ceedb.

📒 Files selected for processing (17)
  • README.md (7 hunks)
  • backend/.env.example (0 hunks)
  • backend/controller/customer.controller.js (2 hunks)
  • backend/controller/reservation.controller.js (4 hunks)
  • backend/index.js (1 hunks)
  • backend/middlewares/authCustomer.js (1 hunks)
  • backend/middlewares/sessionMiddleware.js (1 hunks)
  • backend/models/customer.model.js (2 hunks)
  • backend/models/reservation.model.js (1 hunks)
  • backend/routes/eventRouter.js (2 hunks)
  • backend/routes/reservationRouter.js (1 hunks)
  • frontend/package.json (1 hunks)
  • frontend/src/components/Pages/Dashboard.tsx (1 hunks)
  • frontend/src/components/Pages/Event.jsx (3 hunks)
  • frontend/src/components/Pages/Login.jsx (3 hunks)
  • frontend/src/components/Shared/Navbar.jsx (1 hunks)
  • frontend/src/router/index.jsx (2 hunks)
💤 Files with no reviewable changes (1)
  • backend/.env.example
🧰 Additional context used
🪛 Markdownlint
README.md

283-283: Column: 1
Hard tabs

(MD010, no-hard-tabs)


284-284: Column: 1
Hard tabs

(MD010, no-hard-tabs)


327-327: Column: 1
Hard tabs

(MD010, no-hard-tabs)


328-328: Column: 1
Hard tabs

(MD010, no-hard-tabs)


371-371: Column: 1
Hard tabs

(MD010, no-hard-tabs)


372-372: Column: 1
Hard tabs

(MD010, no-hard-tabs)


459-459: Column: 1
Hard tabs

(MD010, no-hard-tabs)


460-460: Column: 1
Hard tabs

(MD010, no-hard-tabs)


503-503: Column: 1
Hard tabs

(MD010, no-hard-tabs)


504-504: Column: 1
Hard tabs

(MD010, no-hard-tabs)

🪛 Biome
backend/middlewares/sessionMiddleware.js

[error] 2-2: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (26)
backend/middlewares/sessionMiddleware.js (1)

1-12: Verify integration with Remember Me functionality.

Since this middleware is part of the "Remember Me" feature implementation, ensure it properly handles extended session durations.

Let's check for session configuration and remember me implementation:

#!/bin/bash
# Look for session configuration
rg -A 5 "session\.(cookie|maxAge|expires)" --type js

# Look for remember me related code
rg -A 5 "rememberMe|remember_me" --type js
🧰 Tools
🪛 Biome

[error] 2-2: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

backend/models/reservation.model.js (1)

17-21: LGTM! Well-structured schema relationship.

The addition of the customer field with proper MongoDB/Mongoose relationship modeling looks good. The reference to the Customer model and required constraint ensures data integrity.

Let's verify the error handling in the controller:

✅ Verification successful

Error handling for customer field looks robust and complete

The controller implementation properly handles the required customer field with appropriate error handling:

  • Validates customer existence before creating reservation
  • Returns 404 if customer is not found
  • Properly associates reservation with customer using customer._id
  • Includes comprehensive error logging
  • Returns appropriate error responses with status codes

The implementation aligns well with the schema changes and handles the required customer field appropriately. No migration concerns as the controller ensures valid customer references for new reservations.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if the reservation controller properly handles customer validation

# Look for error handling in the controller
rg -A 5 "createReservation|updateReservation" backend/controller/

Length of output: 724


Script:

#!/bin/bash
# Let's get more context around the reservation controller implementation
rg -B 5 -A 15 "createReservation.*try" backend/controller/reservation.controller.js

Length of output: 85


Script:

#!/bin/bash
# Let's try a different approach to get the controller implementation
cat backend/controller/reservation.controller.js

Length of output: 3871

backend/routes/reservationRouter.js (2)

2-2: LGTM: Import statements are properly structured.

The new imports for fetchUserReservations and authenticateCustomer are correctly added and align with the route changes.

Also applies to: 4-4


7-8: Verify error handling for invalid user IDs.

The new routes using :id parameter need proper error handling for invalid user IDs.

Let's verify the error handling implementation:

#!/bin/bash
# Check if the controller handles invalid user IDs
ast-grep --pattern 'fetchUserReservations = async (req, res) => {
  $$$
}'

# Check for error handling patterns in the controller
rg -A 5 "catch.*fetchUserReservations"
backend/routes/eventRouter.js (1)

8-8: Verify error handling in the authentication middleware.

While adding authentication is a good security practice, we should ensure proper error handling in the middleware.

Let's check the error handling implementation:

✅ Verification successful

Error handling in authentication middleware is properly implemented

The middleware has comprehensive error handling with:

  • Token presence check with 401 response
  • Try-catch block for token verification
  • Specific handling for expired tokens (401)
  • Generic token verification errors (403)
  • User existence check (404)
  • Account verification status check (403)
  • Proper logging of errors using the logger utility
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify error handling in authCustomer middleware
# Expected: Should find try-catch blocks and error responses

# Check the middleware implementation
rg -A 10 "const authenticateCustomer" backend/middlewares/authCustomer.js

Length of output: 417


Script:

#!/bin/bash
# Let's get the complete middleware implementation to verify error handling
rg -A 20 "const authenticateCustomer" backend/middlewares/authCustomer.js

# Also check for any custom error handling utilities that might be used
rg "catch|error" backend/middlewares/authCustomer.js

Length of output: 762


Script:

#!/bin/bash
# Let's verify if there's proper error response in the catch block
# and check if the middleware is properly exported
rg -A 5 "catch \(err\)" backend/middlewares/authCustomer.js

# Also check if logger is properly imported
rg "require.*logger|import.*logger" backend/middlewares/authCustomer.js

Length of output: 428

backend/models/customer.model.js (2)

24-31: Formatting changes look good, but verify if intentional.

The removal of trailing commas in the otp, otpExpiry, and isVerified fields maintains consistency with the rest of the schema.

#!/bin/bash
# Check if this is part of a larger formatting effort
rg -l ',$' --type js

Line range hint 1-63: Missing schema fields for "Remember Me" functionality.

The PR objective is to implement a "Remember Me" feature, but the schema lacks necessary fields to support this functionality. Consider adding:

  • A field for refresh tokens
  • Token expiration timestamp
  • Last login timestamp

Here's a suggested addition to the schema:

 const customerSchema = new Schema(
   {
     // ... existing fields ...
+    refreshToken: {
+      type: String,
+      default: null
+    },
+    refreshTokenExpiry: {
+      type: Date,
+      default: null
+    },
+    lastLoginAt: {
+      type: Date,
+      default: null
+    },
     // ... rest of the schema ...
   },
   { timestamps: true }
 );
frontend/package.json (2)

27-27: LGTM! Note about jwt-decode security.

The addition of [email protected] aligns with the "Remember Me" feature implementation. Note that this library is for client-side token payload reading only and doesn't handle token validation, which is the correct approach as token validation should be performed server-side.


27-27: Verify jwt-decode implementation.

Let's ensure the library is being used correctly in the codebase.

✅ Verification successful

Let me gather more information about how jwt-decode is actually used in the Dashboard component.


JWT-decode implementation is correctly used

The implementation in Dashboard.tsx follows security best practices:

  • Only uses jwt-decode for reading the token payload (user ID)
  • No client-side validation attempts
  • Token verification is properly handled server-side (as seen in backend middlewares)
  • Error handling is in place for decoding failures
  • Token is properly passed in Authorization header for API requests
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check jwt-decode usage patterns to ensure correct implementation

# Test 1: Look for jwt-decode imports
echo "Checking jwt-decode import patterns..."
rg "import.*jwt-decode" -A 5

# Test 2: Look for potential direct token validation attempts
# (should be handled server-side)
echo "Checking for token validation patterns..."
rg "verify.*token|validate.*token|isValid.*token"

# Test 3: Look for token decoding usage
echo "Checking token decoding patterns..."
ast-grep --pattern 'jwtDecode($token)'

Length of output: 1050


Script:

#!/bin/bash
# Check the actual implementation in Dashboard.tsx
echo "Checking Dashboard.tsx implementation..."
cat frontend/src/components/Pages/Dashboard.tsx

# Look for any other files that might be using jwt-decode
echo -e "\nChecking for other jwt-decode usages..."
rg "jwtDecode" --type ts --type tsx

Length of output: 4093

frontend/src/router/index.jsx (1)

45-45: ⚠️ Potential issue

Add authentication guard for the dashboard route.

The dashboard route appears to handle user-specific data (reservations) but lacks authentication protection. This could expose sensitive information if accessed directly via URL.

Consider wrapping the route with an auth guard component:

-      <Route path="/dashboard" element={<Profile />} />
+      <Route
+        path="/dashboard"
+        element={
+          <ProtectedRoute>
+            <Profile />
+          </ProtectedRoute>
+        }
+      />

Let's verify if other protected routes use authentication guards:

backend/index.js (2)

17-17: CORS credentials configuration looks good but requires careful verification.

The addition of credentials: true is necessary for the "Remember Me" feature to work with cookies across origins. The implementation is correct and origins are properly restricted.

Let's verify the CORS configuration is consistent across the codebase:

✅ Verification successful

CORS configuration is correctly and consistently implemented

The verification confirms that:

  • There's a single corsOptions configuration with credentials: true properly set
  • This configuration is consistently used across all CORS middleware:
    • Main CORS middleware: app.use(cors(corsOptions))
    • Global preflight: app.options("*", cors(corsOptions))
    • Commented route-specific preflight also references the same config
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any other CORS configurations that might need credentials
# Test: Search for CORS configurations. Expect: All CORS configs to have credentials option set
rg -B 2 -A 2 "cors\(" 

Length of output: 598


Script:

#!/bin/bash
# Let's check the corsOptions configuration to ensure it's properly defined
rg -B 5 -A 5 "corsOptions\s*=" 

Length of output: 539


Line range hint 7-7: Fix typo in error middleware import path.

The import statement contains a typo: errrorMiddleware (three 'r's) should be errorMiddleware.

Let's verify the correct middleware file name and its usage:

Apply this fix:

-const errorMiddleware = require("./middlewares/errrorMiddleware");
+const errorMiddleware = require("./middlewares/errorMiddleware");
frontend/src/components/Pages/Dashboard.tsx (2)

1-5: LGTM! Imports and environment setup are well structured.

The necessary dependencies are properly imported and the environment variable usage follows best practices.

Also applies to: 11-11


1-112: Verify PR scope and objectives.

This file implements a dashboard/profile view for displaying user reservations, but it appears unrelated to the "Remember Me" checkbox functionality mentioned in the PR objectives. Please clarify if this file should be part of this PR or if it should be moved to a separate PR focused on user dashboard functionality.

frontend/src/components/Pages/Login.jsx (1)

25-35: ⚠️ Potential issue

Implement additional security measures

The login implementation needs several security enhancements:

  1. Add CSRF protection
  2. Implement rate limiting for failed attempts
  3. Use more specific error messages without leaking sensitive information
 try {
   const response = await fetch(`${API_URL}/api/user/login`, {
     method: 'POST',
     headers: {
       'Content-Type': 'application/json',
+      'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content,
     },
     body: JSON.stringify({ ...data, rememberMe }),
   });
   const result = await response.json();
-  if (!response.ok) throw new Error(result.message || 'Login failed');
+  if (!response.ok) {
+    switch (response.status) {
+      case 401:
+        throw new Error('Invalid email or password');
+      case 429:
+        throw new Error('Too many login attempts. Please try again later');
+      default:
+        throw new Error('An error occurred during login');
+    }
+  }
backend/controller/customer.controller.js (2)

90-90: LGTM: Schema update for rememberMe is well-defined.

The optional boolean field is correctly added to the schema with proper type validation.


99-101: LGTM: Clean parameter extraction with proper validation.

The destructuring is performed after schema validation, ensuring type safety.

frontend/src/components/Shared/Navbar.jsx (1)

25-25: Verify the dashboard route implementation.

The new PROFILE menu item links to /dashboard. Please ensure that this route is properly configured in your routing setup and that the Dashboard component is implemented.

✅ Verification successful

Let me verify the route configuration with a corrected regex pattern.


Let me check the routing configuration with a corrected command and also verify the component imports.


Let me check the App.jsx for route configuration and examine the component naming discrepancy.


The dashboard route and component implementation are verified, but there's a naming inconsistency.

The /dashboard route is properly configured in router/index.jsx and maps to the Profile component. However, there are some confusing naming patterns:

  • The component is named Profile but lives in Dashboard.tsx
  • The route is /dashboard but imports a component named Profile
  • The navbar menu item is labeled 'PROFILE' but uses /dashboard path

While functionally correct, consider renaming for better consistency:

  • Either rename the file to Profile.tsx to match the component name
  • Or rename the component to Dashboard to match the file and route
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for dashboard route configuration
rg -l "path.*['\"]\/dashboard['\"]" --type js --type jsx --type ts --type tsx

# Search for Dashboard component
fd -e jsx -e tsx -e js -e ts "Dashboard"

Length of output: 270


Script:

#!/bin/bash
# Search for dashboard route configuration with corrected pattern
rg -l 'path.*["\'']/dashboard' --type js --type jsx --type ts --type tsx

# Check the route configuration in common routing files
rg -A 5 'Route.*dashboard' --type js --type jsx --type ts --type tsx

# Examine Dashboard component implementation
cat frontend/src/components/Pages/Dashboard.tsx

Length of output: 4103


Script:

#!/bin/bash
# Search for route configurations with fixed pattern
rg -l "/dashboard" --type js --type jsx --type ts --type tsx

# Check App.tsx or similar files for routing
fd -e tsx -e jsx "App"

# Check if the Profile component is properly imported where routes are defined
rg -l "import.*Profile" --type js --type jsx --type ts --type tsx

Length of output: 228


Script:

#!/bin/bash
# Examine App.jsx content for route configuration
cat frontend/src/App.jsx

# Search for Dashboard/Profile imports and usage with text-based search
rg "Dashboard|Profile" --type-add 'web:*.{js,jsx,ts,tsx}' -t web

Length of output: 879

frontend/src/components/Pages/Event.jsx (3)

17-18: LGTM: Required imports added correctly.

The new imports for navigation and cookie management are appropriately placed and necessary for the authentication feature.


36-36: LGTM: Navigation hook initialized correctly.

The useNavigate hook is properly initialized following React hooks best practices.


Line range hint 17-45: Verify integration with login page's "Remember Me" feature.

The current implementation checks for the authentication token but should be tested with the login page's "Remember Me" functionality to ensure proper integration.

✅ Verification successful

Integration with "Remember Me" feature is properly implemented

The verification shows that:

  • Login.jsx correctly implements the "Remember Me" functionality with proper cookie expiration handling (7 days if checked, 1 hour if not)
  • Event.jsx's authentication check aligns with the cookie-based auth system
  • Cookie handling is consistent across components (Login, Event, Navbar, Dashboard)

The implementation in Event.jsx is appropriate and works correctly with the "Remember Me" feature from the login page.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the integration between Event.jsx and Login page

# Check if Login page implements Remember Me checkbox
echo "Checking for Remember Me implementation in Login page..."
rg -l "Remember Me" "frontend/src/components/Pages/Login"

# Check for consistent token handling
echo "Checking token handling consistency..."
rg "Cookies\.(get|set|remove)\('authToken'\)" "frontend/src/**/*.{jsx,js,tsx,ts}"

Length of output: 507


Script:

#!/bin/bash
# Let's first find the correct paths for Login and Event components
echo "Finding Login and Event component files..."
fd -e jsx -e js "Login|Event"

# Then check for Remember Me and cookie handling
echo "Checking for Remember Me implementation..."
rg -i "remember me" 

echo "Checking cookie handling across files..."
rg "Cookies\.(get|set|remove)\('authToken'\)"

Length of output: 1388

backend/middlewares/authCustomer.js (3)

20-21: Avoid revealing user existence to prevent enumeration attacks

Returning a 404 status with "User not found" may inadvertently disclose whether a user exists, potentially aiding in user enumeration attacks. It's more secure to return a generic authentication error.

[security_issue]

Consider responding with a generic authentication failure:

- return res.status(404).json({ message: "User not found" });
+ return res.status(401).json({ message: "Authentication failed" });

23-25: Prevent account verification status disclosure for enhanced security

Informing the client that the account is not verified can help attackers identify valid user accounts. To mitigate this risk, consider returning a generic error message instead.

[security_issue]

Modify the response to be less specific:

- return res.status(403).json({ message: "Account not verified" });
+ return res.status(401).json({ message: "Authentication failed" });

28-28: Verify that 'user.name' exists in the Customer model

Ensure that the Customer model includes a name property. If user.name is undefined, the log message will be incomplete or misleading.

Run the following script to check if name exists in the Customer model:

✅ Verification successful

The name property is properly defined in the Customer model

The verification confirms that the Customer model (backend/models/customer.model.js) includes a name property of type String that is marked as required, making it safe to use user.name in the log message.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if 'name' property exists in the Customer model

# Find the Customer model file and search for 'name' property definition
fd 'customer.model.js' | while read file; do
  echo "Checking $file"
  rg 'name' "$file"
done

Length of output: 226

backend/controller/reservation.controller.js (2)

33-40: ⚠️ Potential issue

Ensure authorized users can only create reservations for themselves.

There's no check to verify that the authenticated user matches the userId in the request parameters. Without this check, a user could potentially create a reservation on behalf of another user.

Consider adding an authorization check:

 const userId = req.params.id

+ if (req.user.id !== userId) {
+   return res.status(403).json({
+     success: false,
+     message: "You are not authorized to create a reservation for this user.",
+   });
+ }

 const customer = await Customer.findById(userId);

91-129: ⚠️ Potential issue

Implement authorization check when fetching user reservations.

The fetchUserReservations function lacks an authorization mechanism to ensure the requesting user is permitted to access the specified user's reservations. This could lead to unauthorized access to other users' data.

Consider adding an authorization check:

 const userId = req.params.id; // Extract user ID from route parameters

+ if (req.user.id !== userId) {
+   return res.status(403).json({
+     success: false,
+     message: "You are not authorized to access these reservations.",
+   });
+ }

 const reservations = await Reservation.find({ customer: userId }).populate("customer", "name email");

Comment on lines +1 to +2
const sessionMiddleware = (req, res, next) => {
if (req.session.user && req.session.user.id) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider using optional chaining for safer property access.

The session validation can be written more concisely using optional chaining.

- if (req.session.user && req.session.user.id) {
+ if (req?.session?.user?.id) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const sessionMiddleware = (req, res, next) => {
if (req.session.user && req.session.user.id) {
const sessionMiddleware = (req, res, next) => {
if (req?.session?.user?.id) {
🧰 Tools
🪛 Biome

[error] 2-2: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

Comment on lines 1 to 10
const sessionMiddleware = (req, res, next) => {
if (req.session.user && req.session.user.id) {
next(); // Continue if session is valid and has user ID
} else {
res.status(401).send("Invalid session. Please log in again.");
res.status(401).json({
success: false,
message: "Invalid session. Please log in again.",
});
}
}

module.exports = sessionMiddleware;
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Security enhancements needed for session management

The verification reveals several security gaps that support the original review comment:

  1. No CSRF protection is implemented in the codebase
  2. Session configuration has security weaknesses:
    • secure: false in session cookie configuration
    • No explicit sameSite attribute in session cookies
  3. No type validation for user.id in the session middleware
  4. While "Remember Me" functionality is implemented with proper expiration times, the session security measures aren't adequately strengthened to support it

Recommendations:

  • Add CSRF middleware (e.g., csurf package)
  • Enable secure: true for session cookies in production
  • Add sameSite: 'strict' to session cookie configuration
  • Implement type checking for user.id
  • Consider adding helmet middleware for additional security headers
🔗 Analysis chain

Enhance session security measures.

The current session validation could be strengthened by:

  1. Adding type checking for user.id
  2. Implementing session expiration checks
  3. Adding CSRF protection

This is particularly important given the new "Remember Me" functionality being implemented.

Let's verify if CSRF protection is implemented elsewhere:


Let me gather more information about the session and security configurations.


Let me check for additional security configurations and session settings.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for CSRF middleware or protection
rg -i "csrf|csurf" --type js

Length of output: 3678


Script:

#!/bin/bash
# Check for session configuration and security measures
rg -A 5 'app\.use.*session|express-session|cookie-parser|helmet|cors' --type js

# Check for type validation of user.id
ast-grep --pattern 'user.id'

Length of output: 1606


Script:

#!/bin/bash
# Check for session configuration details and security middleware
rg -A 10 'session\(' --type js

# Look for security-related middleware and configurations
rg -A 5 'helmet|secure|sameSite|httpOnly' --type js

Length of output: 2634

🧰 Tools
🪛 Biome

[error] 2-2: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

Comment on lines +7 to +8
router.post("/create/:id", authenticateCustomer, createReservation);
router.get("/get/:id", authenticateCustomer, fetchUserReservations);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

⚠️ Potential issue

Remove unused sessionMiddleware import

The codebase shows a clear transition from session-based authentication to JWT-based authentication:

  • The reservation routes exclusively use authenticateCustomer middleware
  • While sessionMiddleware is still actively used in other routes (feedback, order), it's not used in this file
  • The authentication system uses passport.authenticate("jwt", { session: false }) indicating JWT-based auth

Remove the unused import:

-const sessionMiddleware = require("../middlewares/sessionMiddleware");
🔗 Analysis chain

Verify session handling with new authentication flow.

The routes now use authenticateCustomer but still import unused sessionMiddleware. This suggests a potential transition in the authentication mechanism.

Let's check for any remaining uses of sessionMiddleware:

If sessionMiddleware is no longer used, remove the unused import:

-const sessionMiddleware = require("../middlewares/sessionMiddleware");
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for other uses of sessionMiddleware in the codebase
rg "sessionMiddleware" --type js

Length of output: 117


Script:

#!/bin/bash
# Let's first check if sessionMiddleware is imported in the file
rg -A 2 "require.*sessionMiddleware" backend/routes/reservationRouter.js

# Check for any session-related middleware or authentication across the codebase
rg "session" --type js

# Let's also verify the imports in the router file
head -n 10 backend/routes/reservationRouter.js

Length of output: 2318


router.post("/create",authenticateCustomer, createEvent);
router.get("/all",authenticateCustomer, getEvents);
router.get("/delete",authenticateCustomer, deleteEvent);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Use DELETE HTTP method for delete operations.

The delete route currently uses GET method which doesn't follow REST conventions. DELETE operations should use the DELETE HTTP method.

Apply this change:

-router.get("/delete", authenticateCustomer, deleteEvent);
+router.delete("/delete", authenticateCustomer, deleteEvent);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
router.get("/delete",authenticateCustomer, deleteEvent);
router.delete("/delete",authenticateCustomer, deleteEvent);

Comment on lines +37 to +63
try {
const response = await fetch(
`${API_URL}/api/reservation/get/${userId}`,
{
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${authToken}`, // Pass the token in headers
},
credentials: 'include',
}
);

if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.message || 'Failed to fetch reservations');
}

const data = await response.json();
setReservations(data.data);
} catch (error) {
setError(error.message);
console.error('Error fetching reservations:', error);
} finally {
setLoading(false); // Set loading to false after the fetch operation
}
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance error handling and API URL construction.

  1. The error handling could be more specific to different types of errors (network, auth, etc.).
  2. Consider moving the API endpoint construction to a separate constant or utility.
+      const ENDPOINTS = {
+        GET_RESERVATIONS: (userId: string) => `${API_URL}/api/reservation/get/${userId}`,
+      };
+
       try {
         const response = await fetch(
-          `${API_URL}/api/reservation/get/${userId}`,
+          ENDPOINTS.GET_RESERVATIONS(userId),
           {
             headers: {
               'Content-Type': 'application/json',
               'Authorization': `Bearer ${authToken}`,
             },
             credentials: 'include',
           }
         );

         if (!response.ok) {
+          if (response.status === 401) {
+            throw new Error('Authentication expired. Please login again.');
+          }
+          if (response.status === 404) {
+            throw new Error('No reservations found for this user.');
+          }
           const errorData = await response.json();
           throw new Error(errorData.message || 'Failed to fetch reservations');
         }

Committable suggestion was skipped due to low confidence.

Comment on lines +17 to +18
const user = await Customer.findById(decoded.sub);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Handle invalid user IDs to prevent potential errors

If decoded.sub contains an invalid user ID format, Customer.findById(decoded.sub) may throw an error or return null. It's advisable to handle this scenario explicitly to prevent unexpected behavior.

Consider adding error handling around the database query:

const user = await Customer.findById(decoded.sub);
+ if (user === null) {
+   return res.status(404).json({ message: "User not found" });
+ }

Committable suggestion was skipped due to low confidence.

Comment on lines +8 to +12
const token = req.header("Authorization")?.split(" ")[1];

if (!token) {
return res.status(401).json({ message: "Authorization token is missing" });
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Handle malformed or missing 'Authorization' header to prevent errors

If the Authorization header is missing or doesn't contain a token in the expected format, split(" ")[1] may result in undefined, leading to unexpected behavior. It's important to handle cases where the header is malformed to improve robustness.

Consider modifying the token extraction and adding checks:

- const token = req.header("Authorization")?.split(" ")[1]; 
+ const authHeader = req.header("Authorization");
+ if (!authHeader) {
+   return res.status(401).json({ message: "Authorization header is missing" });
+ }
+ const tokenParts = authHeader.split(" ");
+ if (tokenParts[0] !== "Bearer" || !tokenParts[1]) {
+   return res.status(401).json({ message: "Authorization token is missing or malformed" });
+ }
+ const token = tokenParts[1];
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const token = req.header("Authorization")?.split(" ")[1];
if (!token) {
return res.status(401).json({ message: "Authorization token is missing" });
}
const authHeader = req.header("Authorization");
if (!authHeader) {
return res.status(401).json({ message: "Authorization header is missing" });
}
const tokenParts = authHeader.split(" ");
if (tokenParts[0] !== "Bearer" || !tokenParts[1]) {
return res.status(401).json({ message: "Authorization token is missing or malformed" });
}
const token = tokenParts[1];
if (!token) {
return res.status(401).json({ message: "Authorization token is missing" });
}

Comment on lines +31 to +35
if (err.name === "TokenExpiredError") {
return res.status(401).json({ message: "Token expired" });
}
logger.error("Token verification failed:", err);
return res.status(403).json({ message: "Invalid token" });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance error handling for JWT verification failures

Currently, only TokenExpiredError is specifically handled. Other JWT errors, such as JsonWebTokenError and NotBeforeError, could occur. Handling these errors can provide clearer feedback to the client.

Update the error handling to cover additional JWT errors:

if (err.name === "TokenExpiredError") {
  return res.status(401).json({ message: "Token expired" });
+ } else if (err.name === "JsonWebTokenError") {
+   return res.status(403).json({ message: "Invalid token" });
+ } else if (err.name === "NotBeforeError") {
+   return res.status(403).json({ message: "Token not active" });
} else {
  logger.error("Token verification failed:", err);
  return res.status(403).json({ message: "Invalid token" });
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (err.name === "TokenExpiredError") {
return res.status(401).json({ message: "Token expired" });
}
logger.error("Token verification failed:", err);
return res.status(403).json({ message: "Invalid token" });
if (err.name === "TokenExpiredError") {
return res.status(401).json({ message: "Token expired" });
} else if (err.name === "JsonWebTokenError") {
return res.status(403).json({ message: "Invalid token" });
} else if (err.name === "NotBeforeError") {
return res.status(403).json({ message: "Token not active" });
} else {
logger.error("Token verification failed:", err);
return res.status(403).json({ message: "Invalid token" });
}

Comment on lines 35 to +36

// Create the reservation in the database
const reservation = await Reservation.create(validationResult.data);
const { email, date, guests, time } = validationResult.data;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Use the customer's email from the database instead of the request body.

Using email from the request body can be a security risk, as it allows sending confirmation emails to arbitrary addresses. To prevent potential misuse, obtain the customer's email from the database record.

Apply this diff to use the customer's email:

 const { date, guests, time } = validationResult.data;
+ const email = customer.email;

...

 await sendReservationConfirmation(email, {
   reservationDate: date,
   guests,
   time,
 });

Also applies to: 56-61

Comment on lines 12 to +14
time: z.string(),
email: z.string().email(), // Include email validation in the schema
email: z.string().email(), // Include email validation
userId: z.string().optional(), // Make userId optional for validation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove userId from the validation schema if it's not used from req.body.

The userId field is included in the reservationSchema but is not utilized from req.body in the createReservation function. Including it in the schema could lead to confusion and is unnecessary since userId is extracted from req.params.id.

Apply this diff to remove userId from the validation schema:

     email: z.string().email(), // Include email validation
-    userId: z.string().optional(), // Make userId optional for validation
   })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
time: z.string(),
email: z.string().email(), // Include email validation in the schema
email: z.string().email(), // Include email validation
userId: z.string().optional(), // Make userId optional for validation
time: z.string(),
email: z.string().email(), // Include email validation

@RamakrushnaBiswal
Copy link
Owner

@haseebzaki-07 resolve the conflicts

@haseebzaki-07
Copy link
Contributor Author

@RamakrushnaBiswal done

@RamakrushnaBiswal RamakrushnaBiswal merged commit f5617e3 into RamakrushnaBiswal:main Nov 1, 2024
2 of 3 checks passed
@RamakrushnaBiswal RamakrushnaBiswal added level3 for 45 points gssoc-ext gssoc-extd program hacktoberfest accepted hacktoberfest-accepted repo level2 for 25 points and removed level3 for 45 points labels Nov 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
gssoc-ext gssoc-extd program hacktoberfest accepted hacktoberfest-accepted repo level2 for 25 points
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Topic: Add "Remember Me" checkbox to the login form
2 participants